package com.youlu.campus.admin.live.service.impl;

import com.youlu.campus.admin.base.BaseService;
import com.youlu.campus.admin.live.dto.*;
import com.youlu.campus.admin.utils.DateTimeUtils;
import com.youlu.campus.base.base.LiveStatusEnum;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.live.entity.LiveInfo;
import com.youlu.campus.base.live.entity.LiveRoom;
import com.youlu.campus.admin.live.service.LiveService;
import com.youlu.campus.admin.live.service.PlChannelClient;
import com.youlu.campus.admin.utils.JsonUtil;
import com.youlu.campus.base.sign.SignPlanItemBase;
import lombok.extern.slf4j.Slf4j;
import net.polyv.live.bean.result.channel.PLChannelCreateResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 直播信息接口实现类
 * @author: YangJ
 * @date: 2020/11/23 15:31
 */
@Slf4j
@Service("liveService")
public class LiveServiceImpl extends BaseService implements LiveService {

    private final static String A_CHANNEL_URL = "https://live.polyv.net/web-start/classroom?channelId=";

    private final static String U_CHANNEL_URL = "https://live.polyv.cn/watch/";

    private final static String T_CHANNEL_URL = "https://live.polyv.net/teacher.html";

    @Autowired
    private PlChannelClient plChannelClient;
    
    @Override
    public boolean createLiveRoom(LiveRoomCreateRequest request) {
        log.info("新增直播间信息开始，参数:{}", JsonUtil.toJSON(request));

        //调用第三方直播接口
        PLChannelCreateResult result = plChannelClient.createLive(request.getName(), request.getPwd());
        if(result == null){
            throw new BusinessException("新建直播间错误！");
        }
        LiveRoom liveRoom = mapperFacade.map(request, LiveRoom.class);
        liveRoom.setAnchorUrl(A_CHANNEL_URL+result.getChannelId());
        liveRoom.setUserUrl(U_CHANNEL_URL+result.getChannelId());
        liveRoom.setTeacherUrl(T_CHANNEL_URL);
        liveRoom.setAccounts(plChannelClient.liveChannelAccount(result.getChannelId()));
        mongoTemplate.insert(liveRoom);

        log.info("新增直播间信息结束");

        return true;
    }

    @Override
    public Page<LiveRoomResponse> liveRoomList(LiveRoomQueryRequest request) {
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        long count = mongoTemplate.count(query, LiveRoom.class);

        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<LiveRoom> liveRoomList = mongoTemplate.find(query.with(pageRequest), LiveRoom.class);
        List<LiveRoomResponse> list = liveRoomList.stream().map(liveRoom -> {
            LiveRoomResponse response = mapperFacade.map(liveRoom, LiveRoomResponse.class);
            return response;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    @Override
    public boolean deleteLiveRoom(String id) {

        LiveRoom liveRoom = queryRoom(id);
        liveRoom.setDeleted(true);
        mongoTemplate.save(liveRoom);

        return true;
    }

    private LiveRoom queryRoom(String id){

        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        LiveRoom liveRoom = mongoTemplate.findOne(query, LiveRoom.class);
        if(liveRoom == null){
            throw new BusinessException("查询直播间错误！");
        }
        return liveRoom;
    }

    @Override
    public boolean createLive(LiveCreateRequest request) {


        //校验 - 开始时间大于当前时间1天
        long between = DateTimeUtils.getDaysBetween(new Date(), request.getStartTime());
        if(between < 1){
            throw new BusinessException("直播开始时间应大于当前时间1天！");
        }
        String startDate = DateTimeUtils.formatDate(request.getStartTime(), "yyyyMMdd");
        //校验 - 同一天不能存在多个计划绑定同一个项目
        if(request.getItems() != null){
            List<String> planIds = request.getItems().stream()
                    .map(SignPlanItemBase::getSignPlanId).collect(Collectors.toList());
            if(checkPlan(startDate, planIds)){
                throw new BusinessException("同1天不能存在多个直播排期绑定同一个项目！");
            }
        }
        //校验 - 同一天多个计划的直播口令不能重复
        if(checkWord(startDate,request.getWord())){
            throw new BusinessException("同1天直播排期的直播口令不能重复！");
        }

        LiveInfo liveInfo = mapperFacade.map(request, LiveInfo.class);
        LiveRoom liveRoom = queryRoom(request.getLiveRoomId());
        liveInfo.setStartDate(startDate);
        liveInfo.setLiveRoom(liveRoom);
        liveInfo.setStatus(LiveStatusEnum.PENDING.getCode());
        mongoTemplate.insert(liveInfo);

        return true;
    }

    private boolean checkPlan(String startDate,List planIds){
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        query.addCriteria(Criteria.where("startDate").is(startDate));
        query.addCriteria(Criteria.where("items.signPlanId").in(planIds));
        return mongoTemplate.exists(query, LiveInfo.class);
    }
    private boolean checkWord(String startDate,String word){
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        query.addCriteria(Criteria.where("startDate").is(startDate));
        query.addCriteria(Criteria.where("word").in(word));
        return mongoTemplate.exists(query, LiveInfo.class);
    }

    private LiveInfo queryLive(String id){

        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        LiveInfo liveInfo = mongoTemplate.findOne(query, LiveInfo.class);
        if(liveInfo == null){
            throw new BusinessException("查询直播排期错误！");
        }
        return liveInfo;
    }

    @Override
    public boolean updateLive(LiveUpdateRequest request) {

        LiveInfo liveInfo = queryLive(request.getId());
        if(StringUtils.isNotBlank(request.getTitle())){
            liveInfo.setTitle(request.getTitle());
        }
        if(StringUtils.isNotBlank(request.getImg())){
            liveInfo.setImg(request.getImg());
        }
        if(request.getShow() != null){
            liveInfo.setShow(request.getShow());
        }
        mongoTemplate.save(liveInfo);

        return true;
    }

    @Override
    public boolean deleteLive(String id) {

        LiveInfo liveInfo = queryLive(id);
        liveInfo.setShow(false);
        liveInfo.setStatus(LiveStatusEnum.OFF.getCode());
        liveInfo.setDeleted(true);
        mongoTemplate.save(liveInfo);

        return true;
    }

    @Override
    public boolean updateLiveStatus(String id, Integer status) {

        LiveInfo liveInfo = queryLive(id);
        liveInfo.setStatus(status);
        mongoTemplate.save(liveInfo);

        return true;
    }

    @Override
    public Page<LiveResponse> liveList(LiveQueryRequest request) {

        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        long count = mongoTemplate.count(query, LiveInfo.class);

        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<LiveInfo> liveInfoList = mongoTemplate.find(query.with(pageRequest), LiveInfo.class);
        List<LiveResponse> list = liveInfoList.stream().map(liveInfo -> {
            LiveResponse response = mapperFacade.map(liveInfo, LiveResponse.class);
            response.setStatusStr(LiveStatusEnum.getName(response.getStatus()));
            return response;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    @Override
    public LiveResponse query(String id) {

        LiveInfo liveInfo = queryLive(id);
        LiveResponse response = mapperFacade.map(liveInfo, LiveResponse.class);

        return response;
    }
}
